import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import os

# 设置中文字体，确保图表中文正常显示
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]
plt.rcParams["axes.unicode_minus"] = False  # 解决负号显示问题

class RevenueAnalysis:
    def __init__(self, file_path):
        """
        初始化RevenueAnalysis类
        :param file_path: Excel数据文件路径
        """
        self.file_path = file_path
        self.data = None
        self.output_dir = "analysis_results"
        os.makedirs(self.output_dir, exist_ok=True)

    def load_data(self):
        """
        加载Excel数据
        :return: 加载成功返回True，否则返回False
        """
        try:
            # 检查文件是否存在
            if not os.path.exists(self.file_path):
                print(f"错误: 数据文件不存在 - {self.file_path}")
                return False
            
            # 尝试读取Excel文件
            self.data = pd.read_excel(self.file_path)
            
            # 验证数据是否成功加载
            if self.data is None or len(self.data) == 0:
                print("错误: 数据加载为空，请检查文件内容")
                return False
            
            print(f"数据加载成功，共{len(self.data)}条记录")
            return True
        except Exception as e:
            print(f"数据加载失败: {str(e)}")
            return False

    def data_overview(self):
        """
        数据概览，包括基本信息和统计描述
        """
        if self.data is None:
            print("请先加载数据")
            return

        print("=== 数据基本信息 ===")
        print(self.data.info())

        print("\n=== 数据统计描述 ===")
        print(self.data.describe())

        # 保存概览信息到文本文件
        overview_path = os.path.join(self.output_dir, "data_overview.txt")
        with open(overview_path, "w", encoding="utf-8") as f:
            f.write("=== 数据基本信息 ===\n")
            self.data.info(buf=f)
            f.write("\n=== 数据统计描述 ===\n")
            f.write(str(self.data.describe()))
        print(f"\n数据概览已保存至: {overview_path}")

    def check_missing_values(self):
        """
        检查缺失值并生成报告
        """
        if self.data is None:
            print("请先加载数据")
            return

        missing_values = self.data.isnull().sum()
        missing_percentage = (missing_values / len(self.data)) * 100
        missing_df = pd.DataFrame({
            "缺失值数量": missing_values,
            "缺失值比例(%)": missing_percentage
        })
        missing_df = missing_df[missing_df["缺失值数量"] > 0]

        print("\n=== 缺失值检查结果 ===")
        print(missing_df)

        # 保存缺失值检查结果
        missing_path = os.path.join(self.output_dir, "missing_values.txt")
        missing_df.to_csv(missing_path, encoding="utf-8")
        print(f"缺失值检查结果已保存至: {missing_path}")

    def revenue_distribution(self):
        """
        分析营收分布情况并绘制直方图
        """
        if self.data is None:
            print("请先加载数据")
            return

        # 寻找营收相关列
        revenue_columns = [col for col in self.data.columns if "营收" in col or "收入" in col]
        if not revenue_columns:
            # 如果没有找到明确的营收列，尝试使用所有数值列
            revenue_columns = self.data.select_dtypes(include=[np.number]).columns
            if not revenue_columns:
                print("未找到数值列用于分析")
                return
            print(f"未找到明确的营收列，使用所有数值列进行分析: {list(revenue_columns)}")

        for col in revenue_columns:
            plt.figure(figsize=(10, 6))
            # 兼容旧版本seaborn，使用distplot替代histplot
            sns.distplot(self.data[col].dropna(), kde=True)
            plt.title(f"{col}分布直方图")
            plt.xlabel(col)
            plt.ylabel("频数")
            plt.tight_layout()

            # 保存图表
            plot_path = os.path.join(self.output_dir, f"{col}_distribution.png")
            plt.savefig(plot_path)
            plt.close()
            print(f"营收分布直方图已保存至: {plot_path}")

    def company_comparison(self):
        """
        比较不同公司的营收情况并绘制柱状图
        """
        if self.data is None:
            print("请先加载数据")
            return

        # 寻找公司和营收相关列
        company_col = None
        revenue_col = None
        for col in self.data.columns:
            if "公司" in col or "企业" in col or "名称" in col:
                company_col = col
            if "营收" in col or "收入" in col:
                revenue_col = col

        # 如果没有找到明确的列，使用前几列
        if not revenue_col:
            numeric_cols = self.data.select_dtypes(include=[np.number]).columns
            if numeric_cols:
                revenue_col = numeric_cols[0]
                print(f"未找到明确的营收列，使用第一数值列: {revenue_col}")
            else:
                print("未找到数值列用于分析")
                return

        if not company_col:
            # 如果没有明确的公司列，尝试使用索引或第一列
            if len(self.data.columns) > 0:
                company_col = self.data.columns[0]
                print(f"未找到明确的公司列，使用第一列: {company_col}")
            else:
                print("数据框为空")
                return

        # 按公司分组计算平均营收
        company_revenue = self.data.groupby(company_col)[revenue_col].mean().sort_values(ascending=False)

        # 只显示前20家公司，避免图表过于拥挤
        if len(company_revenue) > 20:
            company_revenue = company_revenue.head(20)
            print(f"仅显示前20家公司的营收比较结果")

        plt.figure(figsize=(15, 8))
        company_revenue.plot(kind="bar")
        plt.title("不同公司营收比较")
        plt.xlabel(company_col)
        plt.ylabel(revenue_col)
        plt.xticks(rotation=45, ha="right")
        plt.tight_layout()

        # 保存图表
        plot_path = os.path.join(self.output_dir, "company_revenue_comparison.png")
        plt.savefig(plot_path)
        plt.close()
        print(f"公司营收比较图已保存至: {plot_path}")

    def correlation_analysis(self):
        """
        分析各数值列之间的相关性并绘制热力图
        """
        if self.data is None:
            print("请先加载数据")
            return

        # 选择数值列
        numeric_cols = self.data.select_dtypes(include=[np.number]).columns
        if len(numeric_cols) < 2:
            print("数据中数值列不足，无法进行相关性分析")
            return

        # 计算相关系数
        corr_matrix = self.data[numeric_cols].corr()

        print("\n=== 相关系数矩阵 ===")
        print(corr_matrix)

        # 绘制热力图
        plt.figure(figsize=(12, 10))
        sns.heatmap(corr_matrix, annot=True, cmap="coolwarm", fmt=".2f")
        plt.title("各数值列相关性热力图")
        plt.tight_layout()

        # 保存热力图
        plot_path = os.path.join(self.output_dir, "correlation_heatmap.png")
        plt.savefig(plot_path)
        plt.close()
        print(f"相关性热力图已保存至: {plot_path}")

        # 保存相关系数矩阵
        corr_path = os.path.join(self.output_dir, "correlation_matrix.csv")
        corr_matrix.to_csv(corr_path, encoding="utf-8")
        print(f"相关系数矩阵已保存至: {corr_path}")

    def run_full_analysis(self):
        """
        运行完整的数据分析流程
        """
        print("===== 上市公司营收数据分析 =====")
        if not self.load_data():
            print("数据加载失败，分析终止")
            return
            
    def generate_summary(self):
        """生成综合分析报告"""
        summary_path = os.path.join(self.output_dir, 'summary.txt')
        with open(summary_path, 'w', encoding='utf-8') as f:
            f.write("# 上市公司营收数据分析报告\n\n")
            f.write("## 一、数据概览\n")
            f.write(f"- 数据集包含 {len(self.data)} 家上市公司的财务数据\n")
            f.write(f"- 主要指标: {', '.join(self.data.select_dtypes(include=['float64']).columns.tolist())}\n\n")
            
            f.write("## 二、关键发现\n")
            f.write("### 1. 营收分布特征\n")
            f.write(f"- 平均营收: {self.data['营业收入'].mean():,.2f} 元\n")
            f.write(f"- 中位数营收: {self.data['营业收入'].median():,.2f} 元\n")
            f.write(f"- 营收范围: {self.data['营业收入'].min():,.2f} 元 - {self.data['营业收入'].max():,.2f} 元\n\n")
            
            f.write("### 2. 公司营收对比\n")
            f.write(f"- 营收最高公司: {self.data.loc[self.data['营业收入'].idxmax()]['证券简称']} ({self.data['营业收入'].max():,.2f} 元)\n")
            f.write(f"- 营收最低公司: {self.data.loc[self.data['营业收入'].idxmin()]['证券简称']} ({self.data['营业收入'].min():,.2f} 元)\n\n")
            
            f.write("### 3. 重要相关性\n")
            corr = self.data.corr()
            top_corr = corr.unstack().sort_values(ascending=False)
            top_corr = top_corr[top_corr < 1.0].drop_duplicates().head(3)
            f.write("- 最强正相关关系:\n")
            for i, (pair, value) in enumerate(top_corr.items(), 1):
                f.write(f"  {i}. {pair[0]} 与 {pair[1]}: {value:.4f}\n")
            
        print(f"综合分析报告已保存至: {summary_path}")

    def run_full_analysis(self):
        """执行完整的数据分析流程"""
        if not self.load_data():
            print("数据加载失败，无法进行分析")
            return
        self.data_overview()
        self.check_missing_values()
        self.revenue_distribution()
        self.company_comparison()
        self.correlation_analysis()
        self.generate_summary()  # 添加综合报告生成
        print("\n===== 数据分析完成 =====")
        print(f"所有分析结果已保存至 {self.output_dir} 文件夹")

if __name__ == "__main__":
    # 指定数据文件路径
    data_file_path = "上市公司营收数据.xlsx"
    analyzer = RevenueAnalysis(data_file_path)
    analyzer.run_full_analysis()